# -*- coding: utf-8 -*-
'''
Created on Mar 19, 2011

@author: kivson
'''
import array
import re
import logging, logging.handlers

class Concluido (Exception):
    pass

class Token(object):

    TITULO = "Titulo"
    AUTOR = "Autor"
    CITACAO = "Citacao"
    AUTOR_GLOBAL = "A Global"

    def __init__(self, tipo, conteudo):
        self.tipo = tipo
        self.valor = array.array('u',conteudo)

    def getValorUnicode(self):
        return self.valor.tounicode()

    def __repr__(self):
        return "<{0}, {1}>".format(self.tipo, self.valor.tounicode())

class Parser(object):
    '''
    Classe para parsear os artigos do wikiquote
    '''
    def __init__(self, pagina, log =None):
        self.pagina= pagina

        self.textoLista = list(pagina)
        #ER do titulo da seção, alguma coisa entres dois grupos de "=="
#        tituloSecao = "==(.*?)=="
#
#        # um asterisco, seguido de possiveis caracters em branco, até encontrar um inicio de outro padrao conhecido.
#        #  [:\*=]  USAR re.DOTALL !!!!!!!!!!!!!!!!!!!!!!!
#        citacaoTipo01 = "\*\s*(.*?)\n"
#
#
#        # dois Pontos, podendo ser seguido ou não por um '-' e alguns espações em branco. depois o nome do autor entre dois bracers
#        autorTipo01 = ":-{,1}\s*\[\[(.*?)\]\]"
#
#        #Dois dois pontos, seguido de um ifem, podendo conter espações em branco depois. o nome do livro vai ate encontrar outro padrao.
#        #USAR re.DOTALL !!!!!!!!!!!!!!!!!!!!!!!
#        livroTipo02 = "::-\s*(.*?)"
#
#
#        autorTipo02 = ":::-{,1}.*?\[\[(.*?)\]\]"
#
#        citacaoTipo03 = "\*\s*'''(.*?)'''\s*(.*?)"
#
#        self.padrao = tituloSecao + "|" + citacaoTipo01 + "|" +  autorTipo01 + "|" + livroTipo02 + "|" + autorTipo02 + "|" + citacaoTipo03
#
#        self.ER = re.compile( self.padrao, re.DOTALL)
        self.tokens = []
        self.tokenAtual = None
        self.concluido = False
        self.log = log



    def getChar(self):
        try:
            return self.textoLista.pop(0)
        except IndexError, e:
            self.concluido = True
            raise Concluido

    def putChar(self, char):
        self.textoLista.insert(0, char)

    def addToken(self):
        self.tokens.append(self.tokenAtual)
        if self.log : self.log.info(str(self.tokenAtual))
        self.tokenAtual = None

    def run(self):
        '''
        Metodo retorna a lista de tokens da string analizada.
        '''

        self.getAutorGlobal()
        try:
            while 1:
                self._s00()
        except Concluido, e:
            pass

    def getTokens(self):
        return self.tokens

    def getAutorGlobal(self):
        padrao = re.compile('\{\{.*(Wiki[pqs].*?= *(\w.+?)\n)', re.DOTALL)
        resp = padrao.findall(self.pagina)
        #print resp
        if resp:
            self.tokenAtual = Token(Token.AUTOR_GLOBAL, resp[0][1])
            self.addToken()


    def _s00(self):
        self.tokenAtual = None
        c = self.getChar()

        if c == '=':
            self._s01()
        elif c =='*':
            self._s04()
        elif c ==':':
            self._s11()
        else:
            return

    def _s01(self):
        c = self.getChar()

        if c == '=':
            self._s02()
        else:
            #vola ao estado 00 (lopp no self.run())
            return

    def _s02(self):

        if not self.tokenAtual:
            self.tokenAtual = Token(Token.TITULO, "")

        c = self.getChar()
        while not c == "=":
            self.tokenAtual.valor.append(c)
            c = self.getChar()
        self._s03()

    def _s03(self):
        c = self.getChar()

        if not c == '=':
            self.tokenAtual.valor.append(c)
            self._s02()
        else:
            self.addToken()
            return

    def _s04(self):
        c = self.getChar()

        while c ==' ':
            c = self.getChar()
        '''
        Removida a parte do analisador lexico responsavel por aceitar:
             ' ' ' autor ' ' ' : citação
        codigo comentado abaixo:
        '''
#        if c == "'":
#            self._s06()
#        else:
#            self.putChar(c)
#            self._s05()
        self.putChar(c)
        self._s05()

    def _s05(self):

        if not self.tokenAtual:
            self.tokenAtual = Token(Token.CITACAO, "")
        c = self.getChar()

        while True:
            if c == "*" or c == ':' or c == '\n':
                if c == "*":
                    self.putChar(c)
                    break
                else:
                    next = self.getChar()
                    trinext = self.getChar()
                    quadrinext = self.getChar()
                    if c == '\n' and (next == '=' or next == '\n' or (next == ':' and (trinext == "[" or trinext == '-' or trinext == ':' or (trinext == " " and quadrinext == "[")))):
                        self.putChar(quadrinext)
                        self.putChar(trinext)
                        self.putChar(next)
                        self.putChar(c)
                        break
                    self.putChar(quadrinext)
                    self.putChar(trinext)
                    self.putChar(next)

            self.tokenAtual.valor.append(c)
            c = self.getChar()

        self.addToken()

    def _s06(self):
        c = self.getChar()

        if c == "'":
            self._s07()

    def _s07(self):
        c = self.getChar()

        if c == "'":
            self._s08()

    def _s08(self):

        if not self.tokenAtual:
            self.tokenAtual = Token(Token.AUTOR, "")
        c = self.getChar()

        while not c == "'":
            self.tokenAtual.valor.append(c)
            c = self.getChar()

        self.addToken()
        self._s09()

    def _s09(self):
        c = self.getChar()

        if c == "'":
            self._s10()

    def _s10(self):
        c = self.getChar()

        if c == "'":
            self._s05()

    def _s11(self):
        c = self.getChar()

        if c == "-" or c == " ":
            self._s12()
        if c == ":":
            self._s11()
        elif c == '[':
            self._s13()

    def _s12(self):
        c = self.getChar()

        while 1:
            if c == '[':
                self._s13()
            elif c == '\n':
                break
            c = self.getChar()

    def _s13(self):
        c = self.getChar()

        if c == '[':
            self._s14()

    def _s14(self):

        if not self.tokenAtual:
            self.tokenAtual = Token(Token.AUTOR, "")
        c = self.getChar()

        while not (c == "]" or c == "|"):
            self.tokenAtual.valor.append(unicode(c))
            c = self.getChar()

        self.addToken()
        #self._s12()








def iniciaLog():

    logging.basicConfig(filename = "../../logs/parser.log", level = logging.DEBUG)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    return logging.getLogger("utilidades.parser")

def testee():
    import mwclient
    import logging
    site = mwclient.Site('pt.wikiquote.org')

    sexo = site.Pages['Sexo']
    simp = site.Pages['Kant']
    Fer = site.Pages['Bhaktivedanta Swami Prabhupada']

    p1 = Parser(sexo.edit(), iniciaLog())
    p2 = Parser(simp.edit(), iniciaLog())
    p3 = Parser(Fer.edit(), iniciaLog())

    print "executando:"
    #p1.run()
    #print p2.tokens
    p2.run()
    #print p2.tokens
    p3.run()
    #print p3.tokens

if __name__ == "__main__":
    import cProfile
    testee()
    #cProfile.run('testee()')




